package net.cyue.web.easyquery.core;

import net.cyue.web.easyquery.core.config.*;
import net.cyue.web.easyquery.core.db.api.ISQLExecutor;
import net.cyue.web.easyquery.core.http.api.IHTTPServer;
import net.cyue.web.easyquery.core.http.handler.api.IWebExceptionHandler;
import net.cyue.web.easyquery.core.http.handler.api.IWebResponseHandler;
import net.cyue.web.easyquery.core.http.handler.api.IWebResultHandler;
import net.cyue.web.easyquery.core.util.TaskUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

/**
 * EasyQueryApplication
 * @param <TContext> 原始服务上下文
 */
public class EasyQueryApplication<TContext> {
    /// 主包名
    public static final String MAIN_PACKAGE_NAME = "net.cyue.web.easyquery";

    private final Logger logger = LoggerFactory.getLogger(this.toString());
    private EasyQueryContext<TContext> context;
    private EasyQueryConfigurationLoader configurationLoader;

    /**
     * 构造函数
     */
    public EasyQueryApplication()
    {
        TaskUtil.runTask(EasyQueryApplicationTaskType.INIT, this);
    }

    /**
     * 构造函数
     * @param context EasyQueryContext
     */
    public EasyQueryApplication(EasyQueryContext<TContext> context)
    {
        this.setContext(context);
        TaskUtil.runTask(EasyQueryApplicationTaskType.INIT, this);
    }

    /**
     * 设置原始服务上下文
     * @param serverContext 原始服务上下文
     * @throws ConfigException 配置异常
     * @throws IOException IO异常
     */
    public void setServerContext(TContext serverContext)
        throws ConfigException, IOException
    {
        this.setContext(new EasyQueryContext<>(serverContext));
    }

    /**
     * 设置 EasyQueryApplication 上下文
     * @param context EasyQueryContext
     */
    public void setContext(EasyQueryContext<TContext> context) {
        this.context = context;
        this.configurationLoader = new EasyQueryConfigurationLoader(this.context);
    }

    /**
     * 设置上下文路径
     * @param path 上下文路径
     */
    public void setContextPath(String path) {
        this.context.setContextPath(path);
    }

    /**
     * 设置 SQL 执行器
     * @param sqlExecutor SQL 执行器
     */
    public void setSQLExecutor(ISQLExecutor sqlExecutor) {
        this.context.setSQLExecutor(sqlExecutor);
    }

    /**
     * 设置 HTTP 服务器
     * @param httpServer HTTP 服务器
     */
    public void setHTTPServer(IHTTPServer httpServer) {
        this.context.setHTTPServer(httpServer);
    }

    /**
     * 设置 WebResult 处理器
     * @param resultHandler 结果处理器
     */
    public void setResultHandler(IWebResultHandler resultHandler) {
        this.context.setResultHandler(resultHandler);
    }

    /**
     * 设置 Web 响应处理器
     * @param responseHandler 设置 HTTP 响应处理器
     */
    public void setResponseHandler(IWebResponseHandler responseHandler) {
        this.context.setResponseHandler(responseHandler);
    }

    /**
     * 设置 Web 异常处理器
     * @param exceptionHandler Web 异常处理器
     */
    public void setExceptionHandler(IWebExceptionHandler exceptionHandler) {
        this.context.setExceptionHandler(exceptionHandler);
    }

    /**
     * 获取原始服务上下文
     * @return 原始服务上下文
     */
    public TContext getServerContext() {
        return this.context.getServerContext();
    }
    /**
     * 获取 EasyQuery 上下文
     * @return EasyQueryContext
     */
    public EasyQueryContext<TContext> getContext() {
        return this.context;
    }


    /**
     * 通过 properties 配置文件运行
     * @param is 配置文件输入流
     * @throws IOException IO 异常
     * @throws ConfigException 配置异常
     */
    public EasyQueryContext<TContext> runByProperties(InputStream is)
        throws IOException, ConfigException
    {
        this.configurationLoader.loadProperties(is);
        return this.context;
    }

    /**
     * 通过 properties 配置文件运行
     * @param properties 配置文件实例对象
     * @throws ConfigException 配置异常
     */
    public EasyQueryContext<TContext> runByProperties(Properties properties) throws ConfigException {
        this.configurationLoader.loadProperties(properties);
        return this.context;
    }

    /**
     * 通过资源文件运行
     * @param resourceName 资源文件名
     * @throws ConfigException 配置异常
     * @throws IOException IO异常
     */
    public EasyQueryContext<TContext> runByResource(String resourceName)
        throws ConfigException, IOException
    {
        this.configurationLoader.loadResource(resourceName);
        return this.context;
    }

    /**
     * 运行
     * @param configuration 配置对象
     * @return
     * @throws ConfigException 配置异常
     */
    public EasyQueryContext<TContext> run(EasyQueryConfiguration configuration)
        throws ConfigException
    {
        this.configurationLoader.load(configuration);
        return this.context;
    }
}
